home *** CD-ROM | disk | FTP | other *** search
- /* -----------------------------------------------------------------------------
-
- info.api ©1999 Dietmar Eilert
-
- Shows information for word under cursor. This client requires a dictionary
- file which lists the known words and the associated help texts. You can use
- the file of the sas-c add-on, ie. "golded:add-ons/sas-c/quickinfo/os3.words".
- The user must specify the name of the dictionary file as startup option of
- this plug-in. Startup options can be specified in the API dialog of GoldED:
- doubleclick on a plug-in name to set its command string.
-
- Dice:
-
- DMAKE
-
- -------------------------------------------------------------------------------
-
- */
-
- #include "defs.h"
-
- /// "prototypes"
-
- // library functions
-
- Prototype LibCall struct APIClient *APIMountClient (__A0 struct APIMessage *, __A1 char *);
- Prototype LibCall void APICloseClient (__A0 struct APIClient *, __A1 struct APIMessage *);
- Prototype LibCall void APIBriefClient (__A0 struct APIClient *, __A1 struct APIMessage *);
- Prototype LibCall void APIFree (__A0 struct APIClient *, __A1 struct APIOrder *);
-
- // private functions
-
- Prototype UBYTE *CheckThisWord (struct PlugInContext *, UBYTE *, UWORD, UWORD);
- Prototype void ClearContainer (struct APIMessage *, struct PlugInContext *);
- Prototype UWORD ComputeX (struct TextFont *, UWORD);
- Prototype UWORD ComputeY (struct TextFont *, UWORD);
- Prototype ULONG DispatchContainer (struct PlugInContext *, struct APIMessage *);
- Prototype ULONG DispatchKey (struct PlugInContext *, struct APIMessage *);
- Prototype struct FileInfoBlock *FileInfo (UBYTE *, struct FileInfoBlock *);
- Prototype void GetVScreenSize (struct Screen *, UWORD *, UWORD *);
- Prototype UWORD Hashcode (UWORD, UWORD, UWORD);
- Prototype struct Dictionary *LoadDictionary (UBYTE *, BOOL);
- Prototype struct Window *Message (UBYTE *, BOOL, struct Window *);
- Prototype struct Window *OpenMessageWin (UBYTE *, BOOL);
- Prototype UBYTE *ReadFile (UBYTE *, ULONG *);
- Prototype BOOL ResolveSymbolicPath(UBYTE *);
- Prototype void ShowInfo (struct APIMessage *, struct PlugInContext *, UBYTE *);
- Prototype WORD memicmp (UBYTE *, UBYTE *, UWORD);
-
- ///
- /// "globals"
-
- struct SignalSemaphore QuickInfoSemaphore; // used to serialize functions
- struct List DictionaryList; // root of dictionaries
-
- // arrays
-
- BOOL IsSPC [256];
- BOOL IsBOUNDARY[256];
-
- ///
- /// "library functions"
-
- LibCall struct APIClient *
- APIMountClient(__A0 struct APIMessage *apiMsg, __A1 char *args)
- {
- struct PlugInContext *context = NULL;
-
- // STATUS/S,IGNORECASE/S,FILE/A
-
- if (args && *args) {
-
- static struct TagItem tags[] = { TAG_DONE };
-
- struct RDArgs *rdArgs;
-
- if (rdArgs = (struct RDArgs *)AllocDosObject(DOS_RDARGS, NULL)) {
-
- LONG argArray[] = { 0, 0, 0 };
-
- UBYTE buffer[MAX_PATHLEN];
-
- // LF-terminate arguments
-
- strcpy(buffer, args);
-
- strcat(buffer, "\12");
-
- // parse arguments (STATUS/S, FILE/K)
-
- rdArgs->RDA_Source.CS_Buffer = buffer;
- rdArgs->RDA_Source.CS_Length = strlen(buffer);
- rdArgs->RDA_Source.CS_CurChr = 0;
- rdArgs->RDA_DAList = 0;
- rdArgs->RDA_Buffer = NULL;
-
- if (ReadArgs("STATUS/S,IGNORECASE/S,FILE/A", argArray, rdArgs)) {
-
- struct Dictionary *dictionary;
-
- if (dictionary = LoadDictionary((UBYTE *)argArray[2], (BOOL)argArray[1])) {
-
- // allocate local data for this plug-in instance (extended APIClient structure)
-
- if (context = (struct PlugInContext *)AllocVec(sizeof(struct PlugInContext), MEMF_PUBLIC | MEMF_CLEAR)) {
-
- context->Dictionary = dictionary;
- context->Status = (BOOL)argArray[0];
- context->Ignorecase = (BOOL)argArray[1];
-
- context->APIClient.api_APIVersion = API_INTERFACE_VERSION;
- context->APIClient.api_Version = 4;
- context->APIClient.api_Name = "Info";
- context->APIClient.api_Info = "Show help text for word under cursor.";
- context->APIClient.api_Commands = NULL;
- context->APIClient.api_Serial = 0;
- context->APIClient.api_Classes = API_CLASS_SYSTEM | API_CLASS_KEY;
-
- // show messages in status line or in a container ?
-
- if (context->Status) {
-
- context->APIClient.api_Area = NULL;
- }
- else {
-
- // prepare the container request
-
- context->APIArea.api_Width = 20;
- context->APIArea.api_Height = 2;
- context->APIArea.api_UnitsX = API_UNITS_FONT;
- context->APIArea.api_UnitsY = API_UNITS_FONT;
- context->APIArea.api_Alignment = API_ALIGN_BOTTOM;
- context->APIArea.api_Style = API_STYLE_STANDARD;
- context->APIArea.api_IDCMP = 0;
-
- context->APIClient.api_Classes |= API_CLASS_CONTAINER;
- context->APIClient.api_Area = &context->APIArea;
- }
- }
- }
-
- FreeArgs(rdArgs);
- }
- else {
-
- if (Fault(IoErr(), "ERROR", buffer, sizeof(buffer)))
-
- Message(buffer, TRUE, NULL);
- }
-
- FreeDosObject(DOS_RDARGS, rdArgs);
- }
- }
- else
- Message("No dictionary file specified !", TRUE, NULL);
-
- return((struct APIClient *)context);
- }
-
- LibCall void
- APICloseClient(__A0 struct APIClient *handle, __A1 struct APIMessage *apiMsg)
- {
- FreeVec(handle);
- }
-
- LibCall void
- APIBriefClient(__A0 struct APIClient *handle, __A1 struct APIMessage *apiMsg)
- {
- struct APIMessage *msg;
-
- // handle notify sent by host program
-
- for (msg = apiMsg; msg; msg = msg->api_Next) {
-
- if (msg->api_State == API_STATE_NOTIFY) {
-
- switch (msg->api_Class) {
-
- case API_CLASS_KEY:
-
- msg->api_Error = DispatchKey((struct PlugInContext *)handle, msg);
-
- break;
-
- case API_CLASS_SYSTEM:
-
- break;
-
- case API_CLASS_CONTAINER:
-
- msg->api_Error = DispatchContainer((struct PlugInContext *)handle, msg);
-
- break;
-
- default:
-
- msg->api_Error = API_ERROR_UNKNOWN;
- }
- }
- }
- }
-
- LibCall void
- APIFree(__A0 struct APIClient *handle, __A1 struct APIOrder *apiOrder)
- {
- // no ressources to be freed
- }
-
- ///
- /// "private functions"
-
- /* ------------------------------- LoadDictionary ------------------------------
-
- Load dictionary if not yet loaded. We simply load the dictionary into a memory
- block, locate the strings in the dictionary (templates and associated help
- texts), NULL-terminate them and build a list of dictionary entries where we
- store pointers to the strings. We also build a very simple hash table where we
- remember the first template beginning with a given character.
-
- Dictionary format (ASCII file, templates MUST BE SORTED PROPERLY):
-
- <template> <help text>
- <template> <help text>
- ...
-
- */
-
- struct Dictionary *
- LoadDictionary(file, ignorecase)
-
- UBYTE *file;
- BOOL ignorecase;
- {
- UBYTE path[MAX_PATHLEN];
- struct Dictionary *dictionary;
-
- // serialize access
-
- ObtainSemaphore(&QuickInfoSemaphore);
-
- strcpy(path, file);
-
- if (ResolveSymbolicPath(path)) {
-
- // search list of resident dictionaries
-
- dictionary = (struct Dictionary *)FindName(&DictionaryList, path);
-
- // dictionary not yet loaded ?
-
- if (dictionary == NULL) {
-
- UBYTE *buffer;
- ULONG size;
-
- if (buffer = ReadFile(path, &size)) {
-
- if (dictionary = (struct Dictionary *)AllocVec(sizeof(struct Dictionary), MEMF_CLEAR | MEMF_PUBLIC)) {
-
- UBYTE *start;
- UBYTE *next;
- UBYTE *last;
-
- strcpy(dictionary->File, path);
-
- dictionary->Data = buffer;
- dictionary->Node.ln_Name = dictionary->File;
-
- NewList(&dictionary->Entries);
-
- // process dictionary
-
- start = buffer;
- last = buffer + size;
-
- for (next = buffer; next < last; ++next) {
-
- // end of entry (example: "xxxx yyyy") detected ?
-
- if (*next == 10) {
-
- // minimum entry "? ?" + <LF>
-
- if (next != start) {
-
- UBYTE *quickinfo;
-
- // NULL-terminate help text
-
- *next = 0;
-
- // find end of template and start of help text
-
- for (quickinfo = start; *quickinfo; ++quickinfo) {
-
- // end of template ?
-
- if (*quickinfo == ' ') {
-
- struct Template *template;
-
- // NULL-terminate template
-
- *quickinfo++ = 0;
-
- if (template = (struct Template *)AllocVec(sizeof(struct Template), MEMF_CLEAR | MEMF_PUBLIC)) {
-
- UWORD hashcode = Hashcode(start[0], start[1], quickinfo - start - 1);
-
- template->Info = quickinfo;
- template->Len = quickinfo - start - 1;
- template->Keyword = start;
-
- AddTail(&dictionary->Entries, &template->Node);
-
- if (dictionary->Hash[hashcode] == NULL)
-
- dictionary->Hash[hashcode] = template;
- }
-
- break;
- }
- else if (ignorecase) {
-
- // case-insensitive dictionary
-
- *quickinfo = toupper(*quickinfo);
- }
- }
- }
-
- start = next + 1;
- }
- }
-
- AddTail(&DictionaryList, &dictionary->Node);
- }
- else {
-
- Message("Out of memory !", TRUE, NULL);
-
- FreeVec(buffer);
- }
- }
- else
- Message("Couldn't load dictionary file", TRUE, NULL);
- }
- }
- else {
-
- Message("Dictionary file not found", TRUE, NULL);
-
- dictionary = NULL;
- }
-
- ReleaseSemaphore(&QuickInfoSemaphore);
-
- return(dictionary);
- }
-
-
- /* --------------------------------- DispatchKey -------------------------------
-
- Dispatch incoming API event
-
- */
-
- ULONG
- DispatchKey(context, apiMsg)
-
- struct PlugInContext *context;
- struct APIMessage *apiMsg;
- {
- ULONG retval = API_ERROR_OK;
-
- switch (apiMsg->api_Action) {
-
- case API_ACTION_RAWKEY:
- case API_ACTION_VANILLAKEY:
-
- {
- struct EditConfig *config;
- UBYTE *info;
-
- config = (struct EditConfig *)apiMsg->api_Instance->api_Environment;
-
- // check word under cursor
-
- if (info = CheckThisWord(context, config->CurrentBuffer, config->CurrentLen, config->Column))
-
- ShowInfo(apiMsg, context, info);
- }
-
- break;
-
- default:
-
- retval = API_ERROR_UNKNOWN;
- }
-
- return(retval);
- }
-
-
- /* -------------------------------- FileInfo -------------------------------------
-
- Get a file's info block.
-
- */
-
- struct FileInfoBlock *
- FileInfo(name, fib)
-
- UBYTE *name;
- struct FileInfoBlock *fib;
- {
- BPTR handle;
-
- memset(fib, 0, sizeof(struct FileInfoBlock));
-
- if (handle = Lock(name, ACCESS_READ)) {
-
- if (Examine(handle, fib) == FALSE)
-
- fib = NULL;
-
- UnLock(handle);
- }
- else
- fib = NULL;
-
- return(fib);
- }
-
-
- /* ------------------------- ResolveSymbolicPath -------------------------------
-
- Make symbolic path (e.g. fonts:) absolute (e.g. dh0:fonts). Writes to path.
- This function fails if <path> doesn't exist.
-
- */
-
- BOOL
- ResolveSymbolicPath(path)
-
- UBYTE *path;
- {
- BPTR lock;
-
- if (lock = Lock(path, ACCESS_READ)) {
-
- NameFromLock(lock, path, MAX_PATHLEN);
-
- UnLock(lock);
-
- return(TRUE);
- }
- else
- return(FALSE);
- }
-
-
- /* ---------------------------------- ReadFile --------------------------------
-
- Alloc buffer and read file to buffer. Buffer has to be FreeVec() later.
-
- */
-
- UBYTE *
- ReadFile(fileName, size)
-
- UBYTE *fileName;
- ULONG *size;
- {
- __aligned struct FileInfoBlock fib;
-
- UBYTE *buffer = NULL;
-
- if (FileInfo(fileName, &fib)) {
-
- if (*size = fib.fib_Size) {
-
- BPTR handle;
-
- if (handle = Open(fileName, MODE_OLDFILE)) {
-
- if (buffer = AllocVec(*size, MEMF_PUBLIC)) {
-
- Read(handle, buffer, *size);
- }
- else
- Message("Out of memory", TRUE, NULL);
-
- Close(handle);
- }
- else
- Message("Couldn't open dictionary file", TRUE, NULL);
- }
- else
- Message("Dictionary file is empty", TRUE, NULL);
- }
- else {
-
- Message("Couldn't examine dictionary file", TRUE, NULL);
-
- *size = 0;
- }
-
- return(buffer);
- }
-
-
- /* ------------------------------- CheckThisWord -------------------------------
-
- Check if quickinfo exists for word at column <column> in buffer <buffer> of
- size <buffersize>. Return 0-terminated info string or NULL.
-
- */
-
- UBYTE *
- CheckThisWord(context, buffer, buffersize, column)
-
- struct PlugInContext *context;
- UBYTE *buffer;
- UWORD buffersize;
- UWORD column;
- {
- UBYTE *text;
- UBYTE *last;
-
- text = buffer + column;
- last = buffer + buffersize;
-
- // find a character of the last word (ignore one white space character and one boundary character if necessary)
-
- if (column && IsSPC[*text]) {
-
- --column;
- --text;
- }
-
- if (column && IsBOUNDARY[*text]) {
-
- --column;
- --text;
- }
-
- // any character found ?
-
- if (IsSPC[*text] == FALSE) {
-
- struct Template *template;
- UBYTE *check;
- UWORD wordlen;
- UWORD hashcode;
- UWORD ascii1;
- UWORD ascii2;
-
- // find beginning of word
-
- while (column) {
-
- if (IsSPC[*(text - 1)])
-
- break;
-
- else {
-
- --text;
- --column;
- }
- }
-
- // determine word length
-
- wordlen = 1;
-
- for (check = text + 1; check < last; ++check) {
-
- // end of word detected ?
-
- if (IsBOUNDARY[*check]) {
-
- ++wordlen;
-
- break;
- }
- else if (IsSPC[*check]) {
-
- break;
- }
- else
- ++wordlen;
- }
-
- // find sensible dictionary entry
-
- if (context->Ignorecase) {
-
- ascii1 = toupper(text[0]);
-
- if (wordlen == 1)
- ascii2 = 0;
- else
- ascii2 = toupper(text[1]);
- }
- else {
-
- ascii1 = text[0];
-
- if (wordlen == 1)
- ascii2 = 0;
- else
- ascii2 = text[1];
- }
-
- hashcode = Hashcode(ascii1, ascii2, wordlen);
-
- // find correct entry (if any)
-
- if (template = context->Dictionary->Hash[hashcode]) {
-
- if (wordlen == 1) {
-
- if (template->Len == 1)
-
- return(template->Info);
- }
- else {
-
- if (context->Ignorecase) {
-
- while (template->Node.ln_Succ) {
-
- if (toupper(template->Keyword[0]) <= ascii1) {
-
- if (toupper(template->Keyword[1]) <= ascii2) {
-
- if (template->Len == wordlen) {
-
- WORD comparison = memicmp(template->Keyword, text, wordlen);
-
- if (comparison == 0)
-
- return(template->Info);
-
- if (comparison > 0)
-
- break;
- }
-
- template = (struct Template *)template->Node.ln_Succ;
- }
- else
- break;
- }
- else
- break;
- }
- }
- else {
-
- while (template->Node.ln_Succ) {
-
- if (template->Keyword[0] <= ascii1) {
-
- if (template->Keyword[1] <= ascii2) {
-
- if (template->Len == wordlen) {
-
- WORD comparison = memcmp(template->Keyword, text, wordlen);
-
- if (comparison == 0)
-
- return(template->Info);
-
- if (comparison > 0)
-
- break;
- }
-
- template = (struct Template *)template->Node.ln_Succ;
- }
- else
- break;
- }
- else
- break;
- }
- }
- }
- }
- }
-
- return(NULL);
- }
-
-
- /* --------------------------------- Hashcode ----------------------------------
-
- Return hashcode (0...2703) for the specified string (specified in form of 1st
- and 2nd character).
-
- */
-
- UWORD
- Hashcode(ascii1, ascii2, len)
-
- UWORD ascii1;
- UWORD ascii2;
- UWORD len;
- {
- // convert characters to A-Z or a-z
-
- if (ascii1 < 'A') {
-
- ascii1 = 'A';
- }
- else if (ascii1 > 'Z') {
-
- if (ascii1 < 'a') {
-
- ascii1 = 'Z';
- }
- else if (ascii1 > 'z')
-
- ascii1 = 'z';
- }
-
- if (ascii2 < 'A') {
-
- ascii2 = 'A';
- }
- else if (ascii2 > 'Z') {
-
- if (ascii2 < 'a') {
-
- ascii2 = 'Z';
- }
- else if (ascii2 > 'z')
-
- ascii2 = 'z';
- }
-
- // calculate final hashcode
-
- if (ascii1 <= 'Z')
- ascii1 = ascii1 - 'A';
- else
- ascii1 = ascii1 - 'a' + 26;
-
- if (ascii2 <= 'Z')
- ascii2 = ascii2 - 'A';
- else
- ascii2 = ascii2 - 'a' + 26;
-
- return(ascii1 * 52 + ascii2);
- }
-
- ///
- /// "gui"
-
- /* ------------------------------ GetVScreenSize -------------------------------
-
- Calculate visible screen rectangle
-
- */
-
- void
- GetVScreenSize(screen, displayW, displayH)
-
- struct Screen *screen;
- UWORD *displayW;
- UWORD *displayH;
- {
- struct Rectangle clip;
-
- // read screen size
-
- if (QueryOverscan(GetVPModeID(&screen->ViewPort), &clip, OSCAN_TEXT)) {
-
- *displayW = clip.MaxX - clip.MinX + 1;
- *displayH = clip.MaxY - clip.MinY + 1;
- }
- else {
-
- *displayW = screen->Width;
- *displayH = screen->Height;
- }
- }
-
-
- /* --------------------------------- ComputeX ----------------------------------
-
- Scale width <value> to match font
-
- */
-
- UWORD
- ComputeX(font, value)
-
- struct TextFont *font;
- UWORD value;
- {
- return((font->tf_XSize * value) / 8);
- }
-
-
- /* --------------------------------- ComputeY ----------------------------------
-
- Resize height <value> to match font
-
- */
-
- UWORD
- ComputeY(font, value)
-
- struct TextFont *font;
- UWORD value;
- {
- return((font->tf_YSize * value) / 8);
- }
-
-
- /* -------------------------------- OpenMessageWin -----------------------------
-
- Open info window. Window is closed automatically after a short delay time if
- <sync> is TRUE.
-
- */
-
- struct Window *
- OpenMessageWin(text, sync)
-
- UBYTE *text;
- BOOL sync;
- {
- struct TextFont *font;
- struct Screen *screen;
- struct Window *win;
- ULONG lock;
-
- win = NULL;
- font = NULL;
-
- // critical stuff (barely legal - don't do this at home, kids ;-)
-
- lock = LockIBase(0);
-
- // find frontmost screen
-
- screen = ((struct IntuitionBase *)IntuitionBase)->ActiveScreen;
-
- // keep system frozen
-
- Forbid();
-
- // enable rendering functions
-
- UnlockIBase(lock);
-
- if (screen) {
-
- struct TextAttr textAttr = { "topaz.font", 8, 0, FPF_DESIGNED };
-
- WORD len, width, height, fontW, fontH, x, y, displayW, displayH, xOffset, yOffset;
-
- GetVScreenSize(screen, &displayW, &displayH);
-
- xOffset = -screen->ViewPort.DxOffset;
- yOffset = -screen->ViewPort.DyOffset;
-
- textAttr = *screen->Font;
-
- if (font = OpenDiskFont(&textAttr)) {
-
- fontW = font->tf_XSize;
- fontH = font->tf_YSize;
-
- CloseFont(font);
- }
- else
- fontW = fontH = textAttr.ta_YSize;
-
- len = strlen(text);
-
- if (len < 30)
-
- len = 30;
-
- width = 20 + fontW * len;
- height = 20 + fontH;
-
- // center window on screen
-
- if (displayW) {
-
- x = ((displayW - width )>>1) + xOffset;
- y = ((displayH - height)>>1) + yOffset;
- }
- else
- x = y = 0;
-
- win = OpenWindowTags(NULL,
-
- WA_PubScreen, screen,
- WA_Left, x,
- WA_Top, y,
- WA_InnerWidth, width,
- WA_InnerHeight, height,
- WA_Flags, WFLG_BORDERLESS | WFLG_SMART_REFRESH | WFLG_RMBTRAP,
- WA_GimmeZeroZero, TRUE,
- TAG_DONE
- );
-
- Permit();
-
- // render window
-
- if (win) {
-
- if (font)
-
- SetFont(win->RPort, font);
-
- win = Message(text, sync, win);
- }
- }
- else
- Permit();
-
- return(win);
- }
-
-
- /* ---------------------------------- Message ----------------------------------
-
- Show message (assume that window size is sufficient)
-
- */
-
- struct Window *
- Message(text, sync, win)
-
- struct Window *win;
- UBYTE *text;
- BOOL sync;
- {
- if (win == NULL) {
-
- win = OpenMessageWin(text, sync);
- }
- else {
-
- struct RastPort *rast;
- struct DrawInfo *drawInfo;
-
- rast = win->RPort;
-
- // render background and frame
-
- if (drawInfo = GetScreenDrawInfo(win->WScreen)) {
-
- SetAPen(rast, drawInfo->dri_Pens[SHINEPEN]);
-
- RectFill(rast, 2, 2, win->Width - 3, win->Height - 3);
-
- SetAPen(rast, drawInfo->dri_Pens[SHADOWPEN]);
- SetBPen(rast, drawInfo->dri_Pens[SHINEPEN ]);
-
- Move(rast, 0, 0);
- Draw(rast, win->Width - 1, 0);
- Draw(rast, win->Width - 1, win->Height - 1);
- Draw(rast, 0, win->Height - 1);
- Draw(rast, 0, 0);
-
- Move(rast, 1, 1);
- Draw(rast, win->Width - 2, 1);
- Draw(rast, win->Width - 2, win->Height - 2);
- Draw(rast, 1, win->Height - 2);
- Draw(rast, 1, 1);
-
- FreeScreenDrawInfo(win->WScreen, drawInfo);
- }
-
- // render new text
-
- Move(rast, 10, 10 + rast->TxBaseline);
-
- Text(rast, text, strlen(text));
-
- if (sync) {
-
- Delay(150);
-
- CloseWindow(win);
-
- win = NULL;
- }
- }
-
- return(win);
- }
-
- ///
- /// "container"
-
-
- /* ----------------------------- DispatchContainer -----------------------------
-
- Handle container-related event
-
- */
-
- ULONG
- DispatchContainer(context, apiMsg)
-
- struct PlugInContext *context;
- struct APIMessage *apiMsg;
- {
- ULONG retval = API_ERROR_OK;
-
- switch (apiMsg->api_Action) {
-
- case API_ACTION_ATTACH:
-
- context->Attached = TRUE;
-
- break;
-
- case API_ACTION_DETACH:
-
- context->Attached = FALSE;
-
- break;
-
- case API_ACTION_PAINT:
- case API_ACTION_REFRESH:
-
- ShowInfo(apiMsg, context, NULL);
-
- break;
-
- default:
-
- retval = API_ERROR_UNKNOWN;
- }
-
- return(retval);
- }
-
-
- /* ------------------------------ ClearContainer -------------------------------
-
- Clear container
-
- */
-
- void
- ClearContainer(apiMsg, context)
-
- struct APIMessage *apiMsg;
- struct PlugInContext *context;
- {
- if (context->Attached && context->Text) {
-
- struct APIInstance *instance;
- struct APIContainer *container;
-
- instance = apiMsg->api_Instance;
-
- if (container = instance->api_Container) {
-
- // container not fully obscured ?
-
- if (container->api_Clipping) {
-
- struct RastPort *rast = container->api_RPort;
-
- SetAPen(rast, container->api_DrawInfo->dri_Pens[BACKGROUNDPEN]);
-
- // clear container
-
- RectFill(rast, container->api_Clipping->MinX, container->api_Clipping->MinY, container->api_Clipping->MaxX, container->api_Clipping->MaxY);
- }
- }
-
- // remember: display is clear
-
- context->Text = NULL;
- }
- }
-
-
- /* --------------------------------- ShowInfo ----------------------------------
-
- Show <text> (show last text if <text> is NULL) in our container (
-
- */
-
- void
- ShowInfo(apiMsg, context, text)
-
- struct APIMessage *apiMsg;
- struct PlugInContext *context;
- UBYTE *text;
- {
- if (context->Status) {
-
- apiMsg->api_Status = text;
-
- }
- else if (context->Attached) {
-
- // (forced) redisplay of last text ?
-
- if (text == NULL) {
-
- text = context->Text;
- }
- else if (context->Text) {
-
- // same text ?
-
- if (strcmp(context->Text, text) == 0)
-
- text = NULL;
- }
-
- if (text) {
-
- struct APIInstance *instance;
- struct APIContainer *container;
-
- instance = apiMsg->api_Instance;
-
- ClearContainer(apiMsg, context);
-
- if (container = instance->api_Container) {
-
- // container not fully obscured ?
-
- if (container->api_Clipping) {
-
- struct TextFont *font;
-
- if (font = OpenDiskFont(container->api_TextAttr)) {
-
- UWORD x0, y0, x1, y1;
- UWORD containerW, textW;
- UWORD containerH, textH;
-
- context->Text = text;
-
- // determine space available for text
-
- x0 = container->api_Clipping->MinX;
- y0 = container->api_Clipping->MinY;
- x1 = container->api_Clipping->MaxX;
- y1 = container->api_Clipping->MaxY;
-
- containerW = x1 - x0 + 1;
- containerH = y1 - y0 + 1;
-
- if ((containerW >= font->tf_XSize) && (containerH >= font->tf_YSize)) {
-
- struct RastPort *rast = container->api_RPort;
-
- UWORD minW = font->tf_XSize + font->tf_XSize;
- UWORD minH = font->tf_YSize + font->tf_YSize;
-
- textW = containerW;
- textH = containerH;
-
- // maintain distance to the container borders (if possible)
-
- if (textW > minW) {
-
- if (textW >= (minW + 8))
- textW -= 8;
- else
- textW -= (textW - minW);
- }
- else
- textW = (textW / font->tf_XSize) * font->tf_XSize;
-
- if (textH > minH) {
-
- if (textH >= (minH + 8))
- textH -= 8;
- else
- textH -= (textH - minH);
- }
- else
- textH = (textH / font->tf_YSize) * font->tf_YSize;
-
- x0 += (containerW - textW) / 2;
- y0 += (containerH - textH) / 2 + font->tf_Baseline;
-
- SetFont(rast, font);
-
- SetAPen(rast, container->api_DrawInfo->dri_Pens[SHADOWPEN]);
-
- // split text into lines
-
- while (*text && (textH >= font->tf_YSize)) {
-
- struct TextExtent textExtent;
- UWORD fit;
-
- if (fit = TextFit(rast, text, strlen(text), &textExtent, NULL, 1, textW, textH)) {
-
- Move(rast, x0, y0);
-
- Text(rast, text, fit);
-
- y0 += font->tf_YSize;
- textH -= font->tf_YSize;
- text += fit;
- }
- else
- break;
- }
- }
-
- CloseFont(font);
- }
- }
- }
- }
- }
- }
-
- ///
- /// "misc"
-
- /* ---------------------------------- memicmp ----------------------------------
-
- case-insensitive string compare (return 0 if identical)
-
- */
-
- WORD
- memicmp(stringA, stringB, len)
-
- UBYTE *stringA;
- UBYTE *stringB;
- UWORD len;
- {
- while (len--) {
-
- UWORD asciiA, asciiB;
-
- asciiA = toupper(*stringA++);
- asciiB = toupper(*stringB++);
-
- if (asciiA > asciiB)
-
- return(+1);
-
- if (asciiA < asciiB)
-
- return(-1);
- }
-
- return(0);
- }
-
- ////
-